const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("Foundation Contract", function () {
    async function deployFoundationFixture() {
        const [owner, otherAccount, donor] = await ethers.getSigners();
        const Foundation = await ethers.getContractFactory("Foundation");
        const foundation = await Foundation.deploy();
        await foundation.deployed();
        return { foundation, owner, otherAccount, donor };
    }

    // 测试用例
    describe("Deployment", function () {
        it("应该设置正确的管理员", async function () {
            const { foundation, owner } = await deployFoundationFixture();
            expect(await foundation.manager()).to.equal(owner.address);
        });

        it("应该设置默认的最低捐款金额为100 wei", async function () {
            const { foundation } = await deployFoundationFixture();
            expect(await foundation.minMoney()).to.equal(100);
        });
    });

    describe("Donations", function () {
        it("应该允许用户捐款并记录捐款详情", async function () {
            const { foundation, donor } = await deployFoundationFixture();
            const donationAmount = ethers.utils.parseEther("1");

            await foundation.connect(donor).usersendMoney(0, { value: donationAmount });
            const donationDetails = await foundation.getDonationDetails(donor.address);
            expect(donationDetails.length).to.equal(1);
            expect(donationDetails[0].amount).to.equal(donationAmount);
        });

        it("应该在捐款后更新总筹款金额", async function () {
            const { foundation, donor } = await deployFoundationFixture();
            const donationAmount = ethers.utils.parseEther("1");

            await foundation.connect(donor).usersendMoney(0, { value: donationAmount });
            const totalRaisedAmount = await foundation.userraisedAmount();
            expect(totalRaisedAmount).to.equal(donationAmount);
        });
    });

    describe("Fundraising Requests", function () {
        it("管理员应该可以创建筹款请求", async function () {
            const { foundation, owner } = await deployFoundationFixture();
            await foundation.connect(owner).createAdminRequest(
                "Title", "Description", owner.address, ethers.utils.parseEther("10"), "photo_hash"
            );
            const request = await foundation.requestions(0);
            expect(request.tittle).to.equal("Title");
            expect(request.description).to.equal("Description");
        });

        it("用户应该可以创建筹款请求", async function () {
            const { foundation, otherAccount } = await deployFoundationFixture();
            await foundation.connect(otherAccount).createUserRequest(
                "User Title", "User Description", ethers.utils.parseEther("5"), "user_photo_hash"
            );
            const userRequest = await foundation.userrequestions(0);
            expect(userRequest.tittle).to.equal("User Title");
            expect(userRequest.description).to.equal("User Description");
        });
    });

    describe("Voting and Execution", function () {
        it("应该允许捐赠者对筹款请求进行投票", async function () {
            const { foundation, owner, donor } = await deployFoundationFixture();
            await foundation.connect(owner).createAdminRequest(
                "Title", "Description", owner.address, ethers.utils.parseEther("10"), "photo_hash"
            );
            await foundation.connect(donor).usersendMoney(0, { value: ethers.utils.parseEther("1") });
            await foundation.connect(donor).voteRequest(0);

            const voters = await foundation.getRequestVoters(0);
            expect(voters).to.include(donor.address);
        });

        it("管理员应该可以在达到条件后执行筹款请求", async function () {
            const { foundation, owner, donor } = await deployFoundationFixture();
            await foundation.connect(owner).createAdminRequest(
                "Title", "Description", owner.address, ethers.utils.parseEther("10"), "photo_hash"
            );
            await foundation.connect(donor).usersendMoney(0, { value: ethers.utils.parseEther("10") });
            await foundation.connect(donor).voteRequest(0);

            // 另一捐赠者投票，以满足超过50%投票者的条件
            const [_, secondDonor] = await ethers.getSigners();
            await foundation.connect(secondDonor).usersendMoney(0, { value: ethers.utils.parseEther("1") });
            await foundation.connect(secondDonor).voteRequest(0);

            await foundation.connect(owner).executeRequest(0);

            const request = await foundation.requestions(0);
            expect(request.completed).to.be.true;
        });
    });

    describe("Top Contributors and Top Voted Requests", function () {
        it("应该获取捐款者的总捐款金额排行", async function () {
            const { foundation, donor, otherAccount } = await deployFoundationFixture();
            await foundation.connect(donor).usersendMoney(0, { value: ethers.utils.parseEther("3") });
            await foundation.connect(otherAccount).usersendMoney(0, { value: ethers.utils.parseEther("5") });

            const [topContributors, topContributions] = await foundation.getTopContributors(2);
            expect(topContributors[0]).to.equal(otherAccount.address);
            expect(topContributions[0]).to.equal(ethers.utils.parseEther("5"));
        });

        it("应该获取投票数最高的筹款请求", async function () {
            const { foundation, owner, donor, otherAccount } = await deployFoundationFixture();
            await foundation.connect(owner).createAdminRequest(
                "Title 1", "Description 1", owner.address, ethers.utils.parseEther("10"), "photo_hash_1"
            );
            await foundation.connect(owner).createAdminRequest(
                "Title 2", "Description 2", owner.address, ethers.utils.parseEther("10"), "photo_hash_2"
            );

            await foundation.connect(donor).usersendMoney(0, { value: ethers.utils.parseEther("1") });
            await foundation.connect(donor).voteRequest(0);
            await foundation.connect(otherAccount).usersendMoney(1, { value: ethers.utils.parseEther("1") });
            await foundation.connect(otherAccount).voteRequest(1);
            await foundation.connect(donor).voteRequest(1); // donor votes for the second request as well

            const topVotedRequests = await foundation.getTopVotedRequests(2);
            expect(topVotedRequests[0].tittle).to.equal("Title 2");
            expect(topVotedRequests[1].tittle).to.equal("Title 1");
        });
    });

    // 其他测试用例
});
